package com.michaelbulava.TFS.vcs.internal.providers;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.history.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.ColumnInfo;
import com.michaelbulava.TFS.vcs.TFSVcs;
import com.michaelbulava.TFS.vcs.internal.TFSFileRevision;
import com.michaelbulava.TFS.vcs.utils.TFSFileUtil;
import com.michaelbulava.TFS.vcs.utils.TFSUtil;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.*;
import com.microsoft.tfs.core.clients.versioncontrol.specs.ItemSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.ChangesetVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.LatestVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.VersionSpec;
import com.microsoft.tfs.util.Check;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by MichaelA on 8/18/2015.
 */
public class TFSHistoryProvider implements VcsHistoryProvider{
    private final Project myProject;

    public TFSHistoryProvider(Project project){
        this.myProject = project;
    }

    @Override
    public VcsDependentHistoryComponents getUICustomization(VcsHistorySession vcsHistorySession, JComponent jComponent) {
        return VcsDependentHistoryComponents.createOnlyColumns(ColumnInfo.EMPTY_ARRAY);
    }

    @Override
    public AnAction[] getAdditionalActions(Runnable runnable) {
        return new AnAction[0];
    }

    @Override
    public boolean isDateOmittable() {
        return false;
    }

    @Nullable
    @Override
    public String getHelpId() {
        return null;
    }

    @Nullable
    @Override
    public VcsHistorySession createSessionFor(FilePath filePath) throws VcsException {
        try{
            Workspace workspace = TFSVcs.getInstance(myProject).getWorkspaceForFile(filePath);
            if (workspace == null)
                return null;
            ItemSpec[] spec = new ItemSpec[]{ TFSFileUtil.createItemSpec(filePath.getPath(), RecursionType.FULL) };
            ExtendedItem[][] extendedItems = workspace.getExtendedItems(spec, DeletedState.ANY, ItemType.ANY);
            if (extendedItems == null || extendedItems.length != 1 || extendedItems[0].length == 0)
                return null;

            List<TFSFileRevision> revisions = getRevisions(myProject, extendedItems[0][0].getTargetServerItem(),
                    filePath.isDirectory(), workspace, LatestVersionSpec.INSTANCE);
            if (revisions.isEmpty())
                return null;
            return createSession(workspace, extendedItems[0][0], revisions);
        } catch(Throwable tr){
            throw new VcsException(tr);
        }
    }

    @Override
    public void reportAppendableHistory(FilePath filePath, VcsAppendableHistorySessionPartner partner) throws VcsException {
        VcsHistorySession session = createSessionFor(filePath);
        partner.reportCreatedEmptySession((VcsAbstractHistorySession)session);
    }

    @Override
    public boolean supportsHistoryForDirectories() {
        return true;
    }

    @Nullable
    @Override
    public DiffFromHistoryHandler getHistoryDiffHandler() {
        return null;
    }

    @Override
    public boolean canShowHistoryFor(VirtualFile virtualFile) {
        Check.notNull(virtualFile, "virtualFile");
        return true;
    }


    public static List<TFSFileRevision> getRevisions(Project project, String serverPath, boolean isDirectory,
                                                     Workspace workspace, VersionSpec versionTo){
        VcsConfiguration vcsConfiguration = VcsConfiguration.getInstance(project);
        int maxCount = vcsConfiguration.LIMIT_HISTORY ? vcsConfiguration.MAXIMUM_HISTORY_ROWS : 2147483647;
        Changeset[] changesets = workspace.getClient().queryHistory(serverPath, new ChangesetVersionSpec(1), 0,
                isDirectory ? RecursionType.FULL :RecursionType.NONE, null, new ChangesetVersionSpec(1), versionTo,
                maxCount, true, true, true, true);
        List<TFSFileRevision> revisions = new ArrayList(changesets.length);
        for(Changeset changeset : changesets){
            Item item = changeset.getChanges()[0].getItem();
            revisions.add(new TFSFileRevision(project, workspace, item.getItemID(),changeset.getDate().getTime(),
                    changeset.getComment(), changeset.getOwner(), changeset.getChangesetID()));
        }
        return revisions;
    }

    private static VcsAbstractHistorySession createSession(final Workspace workspace, final ExtendedItem extendedItem,
                                                           final List<? extends VcsFileRevision> revisions){
        return new VcsAbstractHistorySession(revisions) {
            @Nullable
            @Override
            protected VcsRevisionNumber calcCurrentRevisionNumber() {
                return new VcsRevisionNumber.Int(extendedItem.getLatestVersion());
            }

            @Override
            public VcsHistorySession copy() {
                return TFSHistoryProvider.createSession(workspace, extendedItem, getRevisionList());
            }

            @Nullable
            @Override
            public HistoryAsTreeProvider getHistoryAsTreeProvider() {
                return null;
            }

            public boolean isContentAvailable(VcsFileRevision revision){
                return extendedItem.getItemType() == ItemType.FILE;
            }
        };
    }
}
